//
// Created by benxb on 2021/11/2.
//

#include "mem/active_data_page.h"
#include "common/logger.h"

namespace benxdb {

bool ActiveDataPage::UpdateValue(uint32_t offset, const Value val) {
    if (offset >= GetRecordCount()) {
        LOG_DEBUG("offset out of bound.");
        return false;
    }
    if (val.GetLength() != GetSizeColumn()) {
        LOG_DEBUG("value type does not match.");
        return false;
    }
    char *slot = GetSlotOfRecord(offset);
    memcpy(slot, val.GetData(), val.GetLength());
    return true;
}

bool ActiveDataPage::Append(const Value &val) {
    if (val.GetLength() != GetSizeColumn()) {
        LOG_DEBUG("value type does not match. Expect: %d, given: %d", GetSizeColumn(), val.GetLength());
        return false;
    }
    if (GetFreeSpaceOffset() + val.GetLength() >= PAGE_SIZE) {
        LOG_DEBUG("not any free space in this page.");
        return false;
    }
    memcpy(GetData() + GetFreeSpaceOffset(), val.GetData(), val.GetLength());
    SetFreeSpaceOffset(GetFreeSpaceOffset() + val.GetLength());
    SetRecordCount(GetRecordCount() + 1);
    return true;
}

bool ActiveDataPage::Delete(uint32_t offset) {
    if (offset >= GetRecordCount()) {
        LOG_DEBUG("offset out of bound.");
        return false;
    }
    if (GetRecordCount() > 1) {
        memcpy(GetSlotOfRecord(offset), GetSlotOfLastRecord(), GetSizeColumn());
    }
    SetRecordCount(GetRecordCount()-1);
    SetFreeSpaceOffset(GetFreeSpaceOffset()-GetSizeColumn());
    return true;
}

char* ActiveDataPage::GetSlotOfRecord(uint32_t offset) {
    return GetData() + OFFSET_FIRST_RECORD + offset * GetSizeColumn();
}

char *ActiveDataPage::GetSlotOfLastRecord() {
    BUSTUB_ASSERT(GetRecordCount() > 0, "empty page");
    return GetData() + OFFSET_FIRST_RECORD + (GetRecordCount()-1) * GetSizeColumn();
}

uint32_t ActiveDataPage::GetFreeSpace() {
    return PAGE_SIZE - OFFSET_FIRST_RECORD - GetRecordCount() * GetSizeColumn();
}

void ActiveDataPage::Clear() {
    SetRecordCount(0);
    SetFreeSpaceOffset(OFFSET_FIRST_RECORD);
}

int64_t ActiveDataPage::FlushPage(std::string data_file) {
    std::string out;
    char* firstValuePtr = GetFirstValuePtr();
}

char *ActiveDataPage::GetFirstValuePtr() {
    return GetData() + OFFSET_FIRST_RECORD;
}

}